package com.jkl.gatewayserver.Web.Service;

import Redis.RedisCache;
import com.google.gson.Gson;
import com.jkl.Interface.QueryServer;
import com.jkl.Interface.ZookeeperServer;
import Minio.MinioTemplate;
import com.jkl.entity.*;
import com.jkl.gatewayserver.Tool.JWT.JWTUtils;
import com.jkl.gatewayserver.Tool.RabbitMQ.Producer.Producer;
import com.jkl.pojo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.server.ResponseStatusException;
import reactor.core.publisher.Mono;

import javax.servlet.http.HttpServletResponse;
import java.util.*;

@Slf4j
@Service
public class AppService {
    private final WebClient webClient;
    @DubboReference
    private ZookeeperServer zookeeperServer;
    @DubboReference
    private QueryServer queryServer;
    private final RedisCache redisCache;
    private final Producer producer;
    private final MinioTemplate minio;
    private final Gson gson=new Gson();
    @Autowired
    public AppService(WebClient webClient, RedisCache redisCache, Producer producer, MinioTemplate minio) {
        this.webClient = webClient;
//        this.zookeeperClient = zookeeperClient;
        this.redisCache = redisCache;
        this.producer = producer;
        this.minio = minio;
    }
    //账号登录
    public RAppLoginForm AppVerify(AppLoginForm appLoginForm) throws Exception {
        Account account = queryServer.selectPUSA(appLoginForm.account.getEmail());
        if (account == null) {
            // 用户不存在
            return new RAppLoginForm(0);
        }
        else if (!account.getPassword().equals(appLoginForm.account.getPassword())) {
            // 密码错误
            return new RAppLoginForm(1);
        } else {
            // 登录成功
            String ServerAddr=redisCache.getCacheMapValue(appLoginForm.account.getEmail(),"address");
            if(ServerAddr==null||ServerAddr.isEmpty()||!zookeeperServer.findPath(ServerAddr)){//如果redis存储的信息失效了，那么重新再从zookeeper中获取,并且更新到redis中
                ServerAddr=zookeeperServer.getPath();
                redisCache.setCacheMapValue(appLoginForm.account.getEmail(),"address",ServerAddr);
            }
            if(!Objects.isNull(ServerAddr)){
//                redisCache.setCacheObject(appLoginForm.account.getEmail(),ServerAddr,1, TimeUnit.DAYS);//保存或更新用户在哪台服务器的路由信息,并且设置过期时间为1天
                ServerAddr=ServerAddr.substring(0,ServerAddr.lastIndexOf(":"));
                Map<String, String> payload = new HashMap<>();

                payload.put("email",appLoginForm.getAccount().getEmail());
                payload.put("password",appLoginForm.getAccount().getPassword());
                String token= JWTUtils.getToken(payload);
                if(appLoginForm.account.getAlterTime()!=null&&appLoginForm.account.getAlterTime().equals(account.getAlterTime())){
                    return new RAppLoginForm(2,ServerAddr,token);
                }
                else{
                    return new RAppLoginForm(2,ServerAddr,account,token);
                }
            }
            else {//服务器不在线
                return new RAppLoginForm(0);
            }
        }
    }

    //获取好友列表
    public List<AppFriend> getFriends(String email){
        return queryServer.selectAllFriend(email);
//        return acctFriendMapper.selectAllFriend(email);
    }

    public List<Message> getUnreceivedMessages( String email, Long lastTime){
        return queryServer.selectUnreceivedMessages(email,lastTime);
//        return messageMapper.selectUnreceivedMessages(email,lastTime);
    }
    public List<Message> getAllMessages(String email) {
        return queryServer.selectMessages(email);
//        return messageMapper.selectMessages(email);
    }
    //上传文件
    public ResponseEntity<List<String>> upLoadFile(String fileDir, Map<String, MultipartFile> files) {
        List<String> list=new ArrayList<>();
        for (Map.Entry<String, MultipartFile> entry : files.entrySet()) {
            MultipartFile file = entry.getValue();
            if (!file.isEmpty()) {
                try {
                    //获取文件名
                    String fileName = file.getOriginalFilename();
                    if(!Objects.isNull(fileName)) {
                        list.add(fileName.substring(0,fileName.lastIndexOf(".")));
                        minio.uploadFile(file,fileDir+"/"+fileName, file.getContentType());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    return ResponseEntity.status(500).build();
                }
            }
        }
        //返回上传文件的名字（没有后缀）
        return ResponseEntity.ok(list); // 发送HTTP 200 OK响应
    }
    //下载文件
    public void downloadFile(String filePath, HttpServletResponse response) throws Exception {
        IOUtils.copy(minio.getObject(filePath), response.getOutputStream());
    }
    //搜索好友
    public List<Account> findFriend(String email,String text){
//        return accountMapper.selectLike(email,text);
        return queryServer.selectLike(email,text);
    }

    //获取申请列表
    public List<SCApplication> getApplication(String email){
        return queryServer.selectApplicationInfo(email);
//        return acctFriendMapper.selectApplicationInfo(email);
    }

    //发送好友申请
    public Mono<RCSApplication> buildRelationship(CSApplication application) {
        //通过此函数，将数据发给Netty，然后通过websocket来转发好友申请
        //判断申请信息是否合格
        if (Objects.isNull(application.getFriendId())) {
            return Mono.error(new ResponseStatusException(HttpStatus.BAD_REQUEST, "Receiver is required"));
        }
        //将信息持久化
        producer.sendApplication(gson.toJson(application, CSApplication.class));
        String redirectUrl = getURI(application.getFriendId(),"sendApplication");
        if (redirectUrl == null)//用户不在线
        {
            return Mono.just(new RCSApplication(application));
        }
        application.setNoteName(null);
        //告诉对方你有一个好友申请
        return webClient.post()
                .uri(redirectUrl)
                .contentType(MediaType.APPLICATION_JSON)
                .body(BodyInserters.fromValue(application))
                .exchange()
                .flatMap(response -> {
                    if (response.statusCode().is5xxServerError()) {// HTTP 错误，释放响应体并返回错误
                        return Mono.error(new RuntimeException("HTTP error: " + response.statusCode().value()));
                    }
                    // 成功，释放响应体（如果需要处理响应体，可以在这里处理）
                    return response.releaseBody().thenReturn(new RCSApplication(application));
                })
//                .retryWhen(Retry.fixedDelay(3, Duration.ofSeconds(1))) // 最多重试3次，每次间隔1秒
                .onErrorResume(e -> Mono.just(new RCSApplication(application))); // 处理所有未捕获的异常 ;
    }

    //同意好友申请
    public  Mono<RCSAgree> confirmRelationship(CSAgree agree) {
        if (Objects.isNull(agree.getFriendId())){
            return Mono.error(new ResponseStatusException(HttpStatus.BAD_REQUEST, "Receiver is required"));
        }
        producer.sendAgreeApplication(gson.toJson(agree,CSAgree.class));
        String redirectUrl = getURI(agree.getFriendId(),"sendAgreeApplication");
        Account other=queryServer.selectUSA(agree.getFriendId());//查询好友的基本信息发给自己
        Account self=queryServer.selectUSA(agree.getUserId());//查询自己的基本信息发给好友
//        Account other=accountMapper.selectUSA(agree.getFriendId());
//        Account self=accountMapper.selectUSA(agree.getUserId());
        if (redirectUrl == null)//用户不在线
        {
            return Mono.just(new RCSAgree(agree,other));//返回200状态码
        }
        //发送信息给好友，关系已经确立了
        return webClient.post()
                .uri(redirectUrl)
                .contentType(MediaType.APPLICATION_JSON)
                .body(BodyInserters.fromValue(new SCAgree(agree, self)))
                .exchange()
                .flatMap(response -> {
                    if (response.statusCode().is5xxServerError()) {// HTTP 错误，释放响应体并返回错误
                        return Mono.error(new RuntimeException("HTTP error: " + response.statusCode().value()));
                    }
                    // 成功，释放响应体
                    return response.releaseBody().thenReturn(new RCSAgree(agree,other));
                })
//                .retryWhen(Retry.fixedDelay(3, Duration.ofSeconds(1))) // 最多重试3次，每次间隔1秒
                .onErrorResume(e -> Mono.just(new RCSAgree(agree,other))); // 处理所有未捕获的异常 ;
    }

    public Mono<RMessage> sendMessage(Message msg) {
        //检查请求内容是否正常
        if (Objects.isNull(msg.getReceiver())) {
            return Mono.error(new ResponseStatusException(HttpStatus.BAD_REQUEST, "Receiver is required"));
        }
        producer.sendInsert(gson.toJson(msg, Message.class));
        //查找用户在那个服务器上
        String redirectUrl = getURI(msg.getReceiver(),"sendMessage");
        if (redirectUrl == null)//用户不在线
        {
            return Mono.just(new RMessage(msg));
        }
        return webClient.post()
                .uri(redirectUrl)
                .contentType(MediaType.APPLICATION_JSON)
                .body(BodyInserters.fromValue(msg))
                .retrieve()
                .bodyToMono(RMessage.class);
    }
    private String getURI(String email,String path) {
        if(email!=null){
            String ServerAddr=redisCache.getCacheMapValue(email,"address");
            if(!Objects.isNull(ServerAddr))
                return  "http://"+ServerAddr.substring(0,ServerAddr.indexOf(':'))+ServerAddr.substring(ServerAddr.lastIndexOf(':'))+"/"+path;
        }
        return null;
    }
}
